# Предложения export

Предложение `export` определяет псевдонимы для выбранных членов объекта. 

Например:

```dotty
class BitMap
class InkJet

class Printer:
  type PrinterType
  def print(bits: BitMap): Unit = println("Printer.print()")
  def status: List[String] = ???

class Scanner:
  def scan(): BitMap =
    println("Scanner.scan()")
    BitMap()
  def status: List[String] = ???

class Copier:
  private val printUnit = new Printer { type PrinterType = InkJet }
  private val scanUnit = new Scanner

  export scanUnit.scan
  export printUnit.{status as _, *}

  def status: List[String] = printUnit.status ++ scanUnit.status
```

Два пункта `export` определяют следующие псевдонимы экспорта в классе `Copier`:

```dotty
final def scan(): BitMap            = scanUnit.scan()
final def print(bits: BitMap): Unit = printUnit.print(bits)
final type PrinterType              = printUnit.PrinterType
```

Доступ к ним возможен как изнутри `Copier`, так и снаружи:

```dotty
val copier = new Copier
copier.print(copier.scan())
// Scanner.scan()
// Printer.print()
```

Предложение `export` имеет тот же формат, что и предложение импорта. Его общая форма:

```dotty
export path . { sel_1, ..., sel_n }
```

Оно состоит из выражения квалификатора `path`, которое должно быть стабильным идентификатором 
и за которым следует один или несколько селекторов `sel_i`, определяющих, что получает псевдоним. 
Селекторы могут быть одной из следующих форм:

- Простой селектор `x` создает псевдонимы для всех подходящих членов `path` с именем `x`.
- Селектор переименования `x as y` создает псевдонимы для всех подходящих членов `path`, которым присвоено имя `x`, 
но псевдониму присваивается имя `y` вместо `x`.
- Пропускающий селектор `x as _` предотвращает создание псевдонима `x`.
- Given селектор `given x` содержит необязательную привязку к типу `x`. 
Он создает псевдонимы для всех подходящих экземпляров `given`, которые соответствуют либо `x`, 
либо `Any` если `x` опущен, 
за исключением членов, которые названы предыдущим простым селектором, переименованием или пропуском.
- Селектор с подстановочным знаком `*` создает псевдонимы для всех подходящих членов `path`, 
за исключением экземпляров `given`, синтетических элементов, созданных компилятором, 
и тех членов, которые названы предыдущим простым селектором, переименованием или пропуском.
Замечания:
  - также включены подходящие прокси-конструкторы, даже если они являются синтетическими членами.
  - элементы, созданные `export`, также включаются. 
Они создаются компилятором, но не считаются синтетическими.

Элемент имеет право на `export`, если выполняются все следующие условия:

- его владелец не является базовым классом класса (объекта или trait-а), содержащего предложение `export`,
- элемент не переопределяет конкретное определение, 
владельцем которого является базовый класс класса, содержащего предложение `export`.
- он доступен в разделе `export`,
- это не конструктор и не часть (синтетического) класса объекта,
- это given экземпляр (объявленный с помощью given) тогда и только тогда, 
когда экспорт осуществляется из given селектора.

Возникает ошибка времени компиляции, если простой селектор или селектор переименования 
не идентифицирует какие-либо подходящие элементы.

Члены типа получают псевдонимы в соответствии с определениями типов, 
а члены-термины - в соответствии с определениями методов. 
Псевдонимы экспорта копируют параметры типа и значения элементов, на которые они ссылаются. 
Псевдонимы экспорта всегда `final`. 
Псевдонимы given экземпляров снова определяются как given. 
Псевдонимы расширений снова определяются как расширения. 
Псевдонимы встроенных методов или значений снова определяются как `inline`. 
Других модификаторов, которые можно присвоить псевдониму, нет. 

Это имеет следующие последствия для переопределения:

- Псевдонимы экспорта нельзя переопределить, поскольку они являются `final`.
- Псевдонимы экспорта не могут переопределять конкретные члены в базовых классах, поскольку они не помечены `override`.
- Однако псевдонимы экспорта могут реализовывать отложенные члены базовых классов.

Псевдонимы экспорта для определений общедоступных значений, 
доступ к которым осуществляется без ссылки на private значения в пути к квалификатору, 
помечаются компилятором как "стабильные", 
а их типы результатов являются одноэлементными типами определений с псевдонимами. 
Это означает, что их можно использовать как часть путей стабильных идентификаторов, 
хотя технически они являются методами. 
Например, следующее допустимо:

```dotty
class C { type T }
object O { val c: C = ... }
export O.c
def f: c.T = ...
```

Ограничения:

- Предложения экспорта могут появляться в классах или на верхнем уровне. 
Предложение экспорта не может появиться как оператор в блоке.
- Если предложение экспорта содержит подстановочный знак или селектор given, 
его квалификатору `path` запрещается ссылаться на пакет. 
Это связано с тем, что еще неизвестно, 
как безопасно отслеживать зависимости по шаблону от пакета для целей инкрементной компиляции.
- Переименование экспорта скрывает непереименованные экспорты, соответствующие целевому имени. 
Например, следующее предложение будет недействительным, поскольку `B` скрыто переименованием `A as B`.
`export {A as B, B} // error: B уже скрыто`
- Переименования в предложении экспорта должны иметь попарно разные целевые имена. 
Например, следующий пункт будет недействительным:
`export {A as C, B as C} // error: дублированное переименование`
- Простое переименование экспорта, например `export status as stat` пока не поддерживаются. 
Оно нарушило бы ограничение, что экспортируемый объект не может быть уже членом объекта, содержащего экспорт. 
Это ограничение может быть снято в будущем.


---

**Ссылки:**

- [Scala 3 Reference](https://docs.scala-lang.org/scala3/reference/other-new-features/export.html)
